package com.tul.vapp.servicecenter.start;

import com.tul.cusa.common.log.LogTracerFactory;
import com.tul.cusa.common.log.intf.ILogTracer;
import com.tul.cusa.container.jetty.EmbeddedService;
import com.tul.cusa.container.spring.SpringContextUtils;
import com.tul.vapp.servicecenter.client.ClientFactory;
import com.tul.vapp.servicecenter.client.IConfigClient;
import com.tul.vapp.servicecenter.common.StatusEnum;
import com.tul.vapp.servicecenter.common.SysConfigConstant;
import com.tul.vapp.servicecenter.embedded.EmbeddedZookeeperBean;
import com.tul.vapp.servicecenter.service.IManager;
import com.tul.vapp.servicecenter.util.SysConfigUtil;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.jdbc.ScriptRunner;

import java.io.IOException;
import java.net.UnknownHostException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

/**
 * start main
 *
 * @author wujunlei
 * @version 1.0
 * @since 2018/1/2
 */
public class StartUp {

    /**
     * 日志
     */
    private static final ILogTracer TRACER = LogTracerFactory.getTracer(StartUp.class);

    /**
     * 启动jetty的主方法
     *
     * @param args 默认参数
     * @throws IOException          异常
     * @throws InterruptedException 异常
     */
    public static void main(String[] args) throws IOException, InterruptedException {

        // start zk
        initAndCheckZookeeper();

        //checkDerby
        initAndCheckDerby();

        int port = 55300;
        try {
            port = Integer.parseInt(SysConfigUtil.getProperty(SysConfigConstant.SERVICE_CENTER_PORT));
        } catch (NumberFormatException e) {
            TRACER.error("配置参数异常", e);
        }
        MyEmbeddedService embeddedService = new MyEmbeddedService("0.0.0.0", port);
        embeddedService.setContextPath("/" + SysConfigUtil.getAppName());
        String language = SysConfigUtil.getProperty(SysConfigConstant.LANGUAGE, SysConfigConstant.DEFAULT_LANGUAGE);
        embeddedService.setResourceBase(SysConfigUtil.getAppName() + "-web/dist/" + language);
        String webXmlPath = StartUp.class.getResource("/WEB-INF/web.xml").getPath();
        embeddedService.setDescriptor(webXmlPath);
        embeddedService.setWebAppContextHandler();
        try {
            embeddedService.serverStart();
        } catch (Exception e) {
            TRACER.error("jetty start wrong", e);
        }
    }

    /**
     * init for zookeeper
     */
    private static void initAndCheckZookeeper() {
        String clientPort = SysConfigUtil.getProperty(SysConfigConstant.ZK_PORT, SysConfigConstant.DEFAULT_ZK_PORT);
        String dataDir = SysConfigUtil.getProperty(SysConfigConstant.ZK_DATA);
        String tickTime = SysConfigUtil.getProperty(SysConfigConstant.ZK_TICKTIME);
        String initLimit = SysConfigUtil.getProperty(SysConfigConstant.ZK_INITLIMIT);
        String syncLimit = SysConfigUtil.getProperty(SysConfigConstant.ZK_SYNCLIMIT);
        String zkEmbedded = SysConfigUtil.getProperty(SysConfigConstant.ZK_EMBEDDED);
        Boolean embeddedStart = false;
        if (zkEmbedded.equals("true")) {
            embeddedStart = true;
        }
        EmbeddedZookeeperBean zkBean = new EmbeddedZookeeperBean(embeddedStart, clientPort, dataDir, tickTime,
                initLimit, syncLimit);
        zkBean.init();
    }

    /**
     * check for derby
     */
    public static void initAndCheckDerby() {
        Connection con = null;
        try {
            Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
            con = DriverManager.getConnection("jdbc:derby:sc_db;create=true");
            initScript(con);
        } catch (Exception e) {
            TRACER.error("connect to derby failed...", e);
        } finally {
            try {
                con.close();
            } catch (SQLException e) {

            }
        }
    }

    /**
     * 初始化
     *
     * @param con con
     * @throws IOException
     */
    private static void initScript(Connection con) throws IOException {
        ScriptRunner runner = new ScriptRunner(con);
        runner.setLogWriter(null);
        runner.setErrorLogWriter(null);
        runner.setAutoCommit(true);
        runner.setSendFullScript(false);
        runner.setDelimiter(";");
        // 初始化
        runner.runScript(Resources.getResourceAsReader("stastics/init.sql"));
        // runner.runScript(Resources.getResourceAsReader("stastics/data.sql"));
    }

    /**
     * 自定义启动
     */
    static class MyEmbeddedService extends EmbeddedService {

        /**
         * Constructor.
         *
         * @param host ip
         * @param port port
         * @throws UnknownHostException UnknownHostException
         */
        public MyEmbeddedService(String host, int port) throws UnknownHostException {
            super(host, port);
        }

        @Override
        public void doAfterStart() {
            // 用数据库中已发布的数据更新ZK
            syncApp();
            reportServerStatus();
        }

        /**
         * 上报服务状态
         */
        private void reportServerStatus() {
            ClientFactory.startRemote();
            ClientFactory.init(SysConfigUtil.getAppName());
            IConfigClient configClient = ClientFactory.getClient();
            configClient.report(StatusEnum.PORT, SysConfigUtil.getProperty(SysConfigConstant.SERVICE_CENTER_PORT));
        }

        /**
         * 用数据库中已发布的数据更新ZK
         */
        private void syncApp() {
            IManager manager = SpringContextUtils.getBean(IManager.class);
            // 用release表校验操作表
            manager.sanityCheck();
            // 用release表同步ZK
            manager.sync();
        }
    }
}
